<%+header%>
<script>
	class ModemConfig {
		constructor(cfg_id,title){
			this.cfg_id = cfg_id;
			this.init_view = false;
			this.cbi_map = document.querySelector('.cbi-map');
			this.fieldset = this.create_fieldset(title);
			this.cbi_map.appendChild(this.fieldset);
		}

		update(){
			console.log("update");
			if (this.cb_update) {
				this.cb_update();
			}
		}

		pause(){
			console.log("pause");
		}

		get_config(){
			XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "modem_ctrl")%>', 
			{ 
				"cfg": this.cfg_id,
				"action": this.get_action
			},
				(x, data) => {
					this.config = data[this.config_name];
					if (this.cb_get) {
						this.cb_get(data);
					}
				}
			);
		}

		set_config(config){
			XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "modem_ctrl")%>', 
			{ 
				"cfg": this.cfg_id,
				"action": this.set_action,
				"params": JSON.stringify(config)
			},
				(x, data) => {
					this.config = data[this.config_name];
					if (this.cb_set) {
						this.cb_set(data);
					}
				}
			);
		}

		create_fieldset(title){
			var fieldset = document.createElement('fieldset');
			fieldset.className = "cbi-section";
			var legend = document.createElement('legend');
			legend.innerHTML = title;
			fieldset.appendChild(legend);
			return fieldset;
		}

		createInput(name,value,hint){
			var input = document.createElement('input');
			input.type = "text";
			input.name = name;
			input.value = value;
			input.placeholder = hint;
			return input;
		}

		createBTN(name,cb){
			var btn = document.createElement('input');
			btn.type = "button";
			btn.classList.add("cbi-button");
			btn.value = name;
			btn.addEventListener('click',cb);
			return btn;
		}

		createRadio(name,value){
			var radio = document.createElement('input');
			radio.type = "radio";
			radio.name = name;
			radio.value = value;
			return radio;
		}

		createCheckbox(value){
			var checkbox = document.createElement('input');
			checkbox.type = "checkbox";
			checkbox.value = value;
			return checkbox;
		}

		createTable(){
			let table,tbody;
			table = document.createElement('table');
			table.classList.add("cbi-section-table");
			table.classList.add("table");
			tbody = document.createElement('tbody');
			table.appendChild(tbody);
			return table;
		}

		createDroplist(dict){
			var select = document.createElement('select');
			for (let key in dict) {
				var option = document.createElement('option');
				option.value = key;
				option.innerHTML = dict[key];
				select.appendChild(option);
			}
			return select;
		}

		createInputWithDatalist(name,hint,dict) {
			// 创建输入框
			var input = document.createElement('input');
			input.setAttribute('list', name); // 设置 list 属性以关联 datalist
			input.name = name;
			input.placeholder = hint;

			// 创建 datalist
			var datalist = document.createElement('datalist');
			datalist.id = name;

			// 添加选项到 datalist
			for (let key in dict) {
				var option = document.createElement('option');
				option.value = key;
				datalist.appendChild(option);
			}

			return { input, datalist }; // 返回包含输入框和 datalist 的对象
		}

		createDroplistWithInput(name, hint, dict) {
			var input = this.createInput("","",hint);
			var selector = this.createDroplist(dict);
			var prevous_selected = "";
			var input_tips = "<%:Lost focus to save%>";
			var selector_tips = "<%:Double Click or Right Click to Edit%>";
			var input_descr = this.createDescription(input_tips);
			var selector_descr = this.createDescription(selector_tips);
			input.style.display = "none";
			input_descr.style.display = "none";
			selector.style.width = "100%";
			selector.style.minWidth = "auto";
			// add event to selector
			selector.addEventListener('change', function(event) {
				if (event.target.value.length == 0){
					input.style.display = "";
					selector.style.display = "none";
					input_descr.style.display = "";
					selector_descr.style.display = "none";
					input.value = prevous_selected;
					input.focus();
				}
				else {
					input.style.display = "none";
					selector.style.display = "";
					input_descr.style.display = "none";
					selector_descr.style.display = "";
					prevous_selected = event.target.value;
				}
			});

			// add event listener to seletor : right click or long press or double click: show input
			selector.addEventListener('contextmenu', function(event) {
				event.preventDefault();
				input.style.display = "";
				selector.style.display = "none";
				input_descr.style.display = "";
				selector_descr.style.display = "none";
				input.value = prevous_selected;
				input.focus();
			});
			// add event listener to seletor : hover: show tooltip
			selector.addEventListener('mouseover', function(event) {
				selector.title = selector_tips;
			});
			selector.addEventListener('dblclick', function(event) {
				input.style.display = "";
				selector.style.display = "none";
				input_descr.style.display = "";
				selector_descr.style.display = "none";
				input.value = prevous_selected;
				input.focus();
			});
			// add event listener to input : hover: show tooltip
			input.addEventListener('mouseover', function(event) {
				input.title = input_tips;
			});
			input.addEventListener('blur', function(event) {
				if (event.target.value.length > 0) {
					//clear user input option
					for (let option of selector.options) {
						if (option.type == "userInput") {
							selector.removeChild(option);
						}
					}
					for (let option of selector.options) {
						if (option.value == event.target.value) {
							selector.value = event.target.value;
							selector.dispatchEvent(new Event('change'));
							return;
						}
					}
					var option = document.createElement('option');
					option.value = event.target.value;
					option.innerHTML = event.target.value;
					option.type = "userInput";
					selector.appendChild(option);
					selector.value = event.target.value;
					selector.dispatchEvent(new Event('change'));
				}
				else {
					if (prevous_selected){
						selector.value = prevous_selected;
						selector.dispatchEvent(new Event('change'));
					}
					else{
						//select first not null option
						for (let option of selector.options) {
							if (option.value.length > 0) {
								selector.value = option.value;
								selector.dispatchEvent(new Event('change'));
								return;
							}
						}
						selector.dispatchEvent(new Event('change'));
					}
					
				}
			})

			input.descr = input_descr;
			selector.descr = selector_descr;

			return { input, selector };

		}

		createTD(innerHTML){
			var td = document.createElement('td');
			td.classList.add("cbi-section-table-cell");
			td.classList.add("td");
			td.classList.add("left");
			if (innerHTML) {
				td.innerHTML = innerHTML;
			}
			return td;
		}

		createTH(innerHTML){
			var th = document.createElement('th');
			th.classList.add("cbi-section-table-cell");
			th.classList.add("th");
			if (innerHTML) {
				th.innerHTML = innerHTML;
			}
			return th;
		}

		createTR(){
			var tr = document.createElement('tr');
			tr.classList.add("cbi-section-table-row");
			tr.classList.add("tr");
			return tr;
		}

		createDescription(innerHTML){
			var div = document.createElement('div');
			div.classList.add("cbi-section-descr");
			div.innerHTML = innerHTML;
			return div;
		}

		createTRHeader(){
			var tr = document.createElement('div');
			tr.classList.add("tr");
			tr.classList.add("cbi-section-table-titles");
			tr.classList.add("anonymous");
			return tr;
		}

		init_table(){
			var table = this.createTable();
			this.fieldset.appendChild(table);
			this.tbody = table.querySelector('tbody');
		}

		hide(){
			this.fieldset.style.display = "none";
			this.pause();
		}
		
		show(){
			this.fieldset.style.display = "block";
			console.log("show");
			this.update();
		}
	}

	//锁频功能
	class Lockband extends ModemConfig{
			constructor(cfg_id){
				super(cfg_id,"<%:Lock Band%>");
				this.config_name = "lockband";
				this.get_action = "get_lockband";
				this.set_action = "set_lockband";
				this.lockband_config = {};
				this.checkboxes = {};
				this.available_bandid = {};
				this.band_class_map = {};
				this.init_table();
				this.cb_get = (data) => {
					this.render();
				}
				this.cb_set = (data) => {
					this.get_config();
				}
			}

			set lock(config){
				var band_class = config.band_class;
				var band_id = config.band_id;
				if (!this.lockband_config[band_class].includes(band_id)){
					this.lockband_config[band_class].push(band_id)

				}
				this.checkboxes[band_class][band_id].checked = true;
			}

			set unlock(config){
				var band_class = config.band_class;
				var band_id = config.band_id;
				this.lockband_config[band_class] = this.lockband_config[band_class].filter(x => x != band_id);
				//set checkbox
				this.checkboxes[band_class][band_id].checked = false;
			}

			createCheckbox(band_class,band_name,band_id){
				let checkbox = document.createElement('input');
				checkbox.classList = ["cbi-input-checkbox"];
				checkbox.type = "checkbox";
				checkbox.value = band_id;
				checkbox.setAttribute("display-band",band_name);
				checkbox.addEventListener("change",() => {
					if (checkbox.checked){
						this.lock = { "band_class": band_class, "band_id": band_id };
					}
					else{
						this.unlock = { "band_class": band_class, "band_id": band_id };
					}
				});
				
				this.checkboxes[band_class][band_id] = checkbox;
				if (this.lockband_config[band_class].includes(band_id)) {
					this.lock = { "band_class": band_class, "band_id": band_id };
				}
			}
		
			createcheckboxes(band_class){
				var band = this.config[band_class];
				var available_band = band.available_band;
				var lock_band = band.lock_band;
				this.lockband_config[band_class] = lock_band;
				if ( available_band.length == 0) {
					return;
				}
				if (this.checkboxes[band_class] == undefined) {
					this.checkboxes[band_class] = {};
				}
				if (this.available_bandid[band_class] == undefined) {
					this.available_bandid[band_class] = [];
				}
				
				for (let band_cfg of available_band) {
					let band_name = band_cfg.band_name;
					let band_id = band_cfg.band_id;
					if (this.available_bandid[band_class].includes(band_id) == false) {
						this.available_bandid[band_class].push(band_id);
					}
					this.createCheckbox(band_class,band_name,band_id);
				}
			}

			submit(band_class)
			{
				var sorted = this.lockband_config[band_class].sort();
				var config = '';
				for (let band_id of sorted) {
					config += band_id + ",";
				}
				var lockband_cfg = {
					"band_class": band_class,
					"lock_band": config.slice(0,-1)
				}
				var cfg_string = JSON.stringify(lockband_cfg);
				this.set_config(cfg_string);
			}

			select_all(band_class){
				//if all selected, then unselect all
				let lockall = this.lockband_config[band_class].length != this.available_bandid[band_class].length;
				for (let band_id of this.available_bandid[band_class]) {
					if (lockall) {
						this.lock = { "band_class": band_class, "band_id": band_id };
					}
					else{
						this.unlock = { "band_class": band_class, "band_id": band_id };
					}
				}
			}

			render() {
				for (let band_class in this.band_class_map){
					if (this.config[band_class] == undefined) {
						this.band_class_map[band_class].header.style.display = "none";
						this.band_class_map[band_class].tr.style.display = "none";
						this.band_class_map[band_class].select_all_btn.style.display = "none";
						this.band_class_map[band_class].submit_btn.style.display = "none";
					}
					else{
						this.band_class_map[band_class].header.style.display = "";
						this.band_class_map[band_class].tr.style.display = "";
						this.band_class_map[band_class].select_all_btn.style.display = "";
						this.band_class_map[band_class].submit_btn
					}
				}
				for (let band_class in this.config) {
					let header, tr, td, select_all_btn, submit_btn;
					this.createcheckboxes(band_class);
					if (this.band_class_map[band_class] == undefined)
					{
						this.createBandTable(band_class);
					}
					header = this.band_class_map[band_class].header;
					tr = this.band_class_map[band_class].tr;
					select_all_btn = this.band_class_map[band_class].select_all_btn;
					submit_btn = this.band_class_map[band_class].submit_btn
					td = document.createElement('td');
					td.classList.add("cbi-section-table-cell");
					td.classList.add("td")
					td.style.display = "flex";
					td.style.flexWrap = "wrap";
					//clear tr
					while (tr.firstChild) {
						tr.removeChild(tr.firstChild);
					}
					tr.appendChild(td);
					for (let checkbox in this.checkboxes[band_class]) {
						let display_value = this.checkboxes[band_class][checkbox].getAttribute("display-band");
						let span = document.createElement('span');
						span.innerHTML = display_value;
						let band_container=document.createElement('span');
						band_container.classList.add("band-container");
						band_container.appendChild(this.checkboxes[band_class][checkbox]);
						band_container.appendChild(span);
						td.appendChild(band_container);
					}
				}

			}

			createBandTable(band_class){
				let tr_header, th, tr, td, select_all_btn, submit_btn;
				tr_header = document.createElement('div');
				tr_header.className = "tr cbi-section-table-titles anonymous";
				th = document.createElement('div');
				th.className = "th cbi-section-table-cell";
				th.innerHTML = band_class;
				tr_header.appendChild(th);
				tr = document.createElement('tr');
				tr.className = "tr cbi-section-table-row";
				select_all_btn = this.createBTN("<%:Select All%>", () => {
						this.select_all(band_class);
					});
				submit_btn = this.createBTN("<%:Submit%>", () => {
						this.submit(band_class);
					});
				this.band_class_map[band_class] = {
						"header": tr_header,
						"tr": tr,
						"select_all_btn": select_all_btn,
						"submit_btn": submit_btn
					}
				this.tbody.appendChild(tr_header);
				this.tbody.appendChild(tr);
				this.tbody.appendChild(select_all_btn);
				this.tbody.appendChild(submit_btn);

			}

			update() {
				console.log(JSON.stringify(this.lockband_config));
				console.log(JSON.stringify(this.available_bandid));
				console.log(JSON.stringify(this.band_class_map));
				console.log(JSON.stringify(this.config));
				this.get_config();
			}

	}

	class RatPrefer extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:Rat Prefer%>");
			this.config_name = "network_prefer";
			this.get_action = "get_network_prefer";
			this.set_action = "set_network_prefer";
			this.selected_rat = [];
			this.available_rat = [];
			this.init_table();
			this.create_submit_btn();
			}

		cb_get(data){
				//clear selected_rat
				this.selected_rat = [];
				//clear available_rat
				this.available_rat = [];
				for (let key in this.config){
					
					if (this.config[key] == 1) {
						this.selected_rat.push(key);
					}
					this.available_rat.push(key);

				}
				
				this.render_checkbox();
				this.render_current_mode();
			}
		cb_set(data){
				this.get_config();
			}

		render_current_mode(){
			let selected_mode = []
			for (let rat in this.config) {
				if (this.config[rat] == 1) {
					selected_mode.push(rat);
				}
			}
			this.current_mode = selected_mode.join(',');
			this.current_mode_td.innerHTML = this.current_mode;
		}

		render_checkbox(){
			if (this.init_view == false) {
				this.init_ele();
				this.init_view = true;
			}
			this.createCheckboxes();
		}

		create_submit_btn(){
			var submit_btn = this.createBTN("<%:Submit%>",() => {
				this.submit();
			});
			this.fieldset.appendChild(submit_btn);
		}

		createCheckbox(rat){
			var checkbox = document.createElement('input');
			checkbox.type = "checkbox";
			checkbox.value = rat;
			checkbox.addEventListener('change',() => {
				if (checkbox.checked) {
					this.selected_rat.push(rat);
				}
				else{
					this.selected_rat = this.selected_rat.filter(x => x != rat);
				}
			});
			return checkbox;
		}

		createCheckboxes(){
			//clear select_td
			while (this.select_td.firstChild) {
				this.select_td.removeChild(this.select_td.firstChild);
			}
			var network_prefer = this.config;
			for (let rat of this.available_rat) {
				var checkbox = this.createCheckbox(rat);
				if (this.selected_rat.includes(rat)) {
					checkbox.checked = true;
				}
				var span = document.createElement('span');
				span.innerHTML = rat;
				this.select_td.appendChild(checkbox);
				this.select_td.appendChild(span);
			}
		}

		update(){
			this.get_config();
		}

		submit(){
			this.set_config(JSON.stringify(this.selected_rat));
		}

		init_ele(){
			var header_tr,current_mode_th,select_th,setting_tr,current_mode_td,select_td;
			header_tr = this.createTRHeader();
			current_mode_th = this.createTH("<%:Current Mode%>");
			select_th = this.createTH("<%:Setting%>");
			setting_tr = this.createTR();
			current_mode_td = this.createTD();
			select_td = this.createTD();
			header_tr.appendChild(current_mode_th);
			header_tr.appendChild(select_th);
			setting_tr.appendChild(current_mode_td);
			setting_tr.appendChild(select_td);
			this.tbody.appendChild(header_tr);
			this.tbody.appendChild(setting_tr);
			this.current_mode_td = current_mode_td;
			this.select_td = select_td;

		}
	}
	
	class DialMode extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:Dial Mode%>");
			this.config_name = "mode";
			this.get_action = "get_mode";
			this.set_action = "set_mode";
			this.avalibale_mode = [];
			this.selected_mode = null;
			this.init_table();
			this.td_map = {
				"current_mode": null,
				"radio_div": null,
			}
			this.cb_get = (data) => {
				this.render();
			}
			this.cb_set = (data) => {
				this.get_config();
			}
		}

		render(){
			if (this.td_map["current_mode"] == null) {
				this.init_ele();
			}

			for (let key in this.config){
				if (this.avalibale_mode.includes(key) == false)
				{
					this.avalibale_mode.push(key);
				}
				if (this.config[key] == 1) {
					this.selected_mode = key;
					this.td_map.current_mode.innerHTML = key;
				}
			}
			this.create_mode_radio();
			
		}

		init_ele(){
			var radio_div_th, current_mode_th, radio_div, current_mode, header_tr, setting_tr;
			header_tr = document.createElement('div');
			header_tr.className = "tr cbi-section-table-titles anonymous";
			radio_div_th = document.createElement('div');
			radio_div_th.className = "th cbi-section-table-cell";
			radio_div_th.innerHTML = "<%:Dial Mode%>";
			current_mode_th = document.createElement('div');
			current_mode_th.className = "th cbi-section-table-cell";
			current_mode_th.innerHTML = "<%:Current Mode%>";
			setting_tr = document.createElement('div');
			setting_tr.className = "tr cbi-section-table-row";
			radio_div = document.createElement('div');
			radio_div.className = "td cbi-section-table-cell left";
			current_mode = document.createElement('div');
			current_mode.className = "td cbi-section-table-cell left";
			header_tr.appendChild(current_mode_th);
			header_tr.appendChild(radio_div_th);
			
			setting_tr.appendChild(current_mode);
			setting_tr.appendChild(radio_div);
			
			this.tbody.appendChild(header_tr);
			this.tbody.appendChild(setting_tr);
			this.td_map["radio_div"] = radio_div;
			this.td_map["current_mode"] = current_mode;
			this.mode_btn = this.createBTN("<%:Submit%>",() => {
				this.set_config(this.selected_mode);
			});
			this.tbody.appendChild(this.mode_btn);
		}

		create_mode_radio(){
			while (this.td_map.radio_div.firstChild) {
					this.td_map.radio_div.removeChild(this.td_map.radio_div.firstChild);
				}
			for (let mode of this.avalibale_mode) {
				let radio = this.createRadio("mode",mode);
				if (mode == this.selected_mode) {
					radio.checked = true;
				}
				radio.addEventListener('change',() => {
					this.selected_mode = mode;
				});
				
				let span = document.createElement('span');
				span.innerHTML = mode;
				//clear radio_div
				
				this.td_map.radio_div.appendChild(radio);
				this.td_map.radio_div.appendChild(span);
			}
			
		}
	
		update(){
			this.get_config();
		}
	}

	class NeighborCell extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:Neighbor Cell%>");
			this.config_name = "neighborcell";
			this.get_action = "get_neighborcell";
			this.set_action = "set_neighborcell";
			this.task = null;
			this.init_nc_table();			
		}
		
		pause(){
			if (this.task != null) {
				clearInterval(this.task);
			}
		}

		update(){
			this.task = setInterval(() => {
				this.get_config();
			},10000);
		}

		nr_options(){
				if (this.rat_input.selectedIndex == 0) {
					this.band_tr.style.display = "none";
					this.scs_tr.style.display = "none";
				}
				else{
					this.band_tr.style.display = "";
					this.scs_tr.style.display = "";
				}
			}

		init_nc_table(){
			var neighborcell_table,setting_table,status_table ;
			neighborcell_table = this.createTable();
			status_table = this.createTable();
			setting_table = this.createTable();
			
			this.fieldset.appendChild(neighborcell_table);
			this.fieldset.appendChild(status_table);
			this.fieldset.appendChild(setting_table);

			this.neighborcell_table = neighborcell_table.querySelector('tbody');
			this.status_table = status_table.querySelector('tbody');
			this.setting_table = setting_table.querySelector('tbody');

			var pci_tr,arfcn_tr,band_tr,scs_tr,header,td,td1,th,pci_input,arfcn_input,band_input,scs_input,rat_input,rat_tr;
			var status_th,status_trh;
			header = this.createTRHeader();
			th = this.createTH("<%:Lock Cell Setting%>");
			header.appendChild(th);

			rat_input = this.createDroplist({0:"LTE",1:"NR"});
			rat_tr = this.createTR();
			td = this.createTD("<%:RAT%>");
			td1 = this.createTD();
			td1.appendChild(rat_input);
			rat_tr.appendChild(td);
			rat_tr.appendChild(td1);


			pci_tr = this.createTR();
			td = this.createTD("<%:PCI%>");
			pci_input = this.createInput("pci","");
			td1 = this.createTD();
			td1.appendChild(pci_input);
			pci_tr.appendChild(td);
			pci_tr.appendChild(td1);

			arfcn_tr = this.createTR();
			td = this.createTD("<%:ARFCN%>");
			arfcn_input = this.createInput("arfcn","");
			td1 = this.createTD();
			td1.appendChild(arfcn_input);
			arfcn_tr.appendChild(td);
			arfcn_tr.appendChild(td1);
			
			band_tr = this.createTR();
			td = this.createTD("<%:Band%>");
			band_input = this.createInput("band","");
			td1 = this.createTD();
			td1.appendChild(band_input);
			band_tr.appendChild(td);
			band_tr.appendChild(td1);

			scs_tr = this.createTR();
			td = this.createTD("<%:SCS%>");
			scs_input = this.createDroplist({0:"15KHZ",1:"30KHZ"});
			td1 = this.createTD();
			td1.appendChild(scs_input);
			scs_tr.appendChild(td);
			scs_tr.appendChild(td1);

			
			status_th = this.createTH("<%:Status%>");
			status_trh = this.createTRHeader();
			status_trh.appendChild(status_th);
			this.status_table.appendChild(status_trh);

			this.pci_input = pci_input;
			this.arfcn_input = arfcn_input;
			this.band_input = band_input;
			this.scs_input = scs_input;
			this.rat_input = rat_input;
			this.band_tr = band_tr;
			this.scs_tr = scs_tr;
			this.band_tr.style.display = "none";
			this.scs_tr.style.display = "none";
			this.rat_input.addEventListener('change',()=>{
				this.nr_options();
			});

			var submit_btn = this.createBTN("<%:Submit%>",() => {
				var config = {
					"rat": this.rat_input.selectedIndex,
					"pci": this.pci_input.value,
					"arfcn": this.arfcn_input.value,
					"band": this.band_input.value,
					"scs": this.scs_input.selectedIndex
				}
				this.set_config(JSON.stringify(config));
			});

			this.setting_table.appendChild(header);
			this.setting_table.appendChild(rat_tr);
			this.setting_table.appendChild(pci_tr);
			this.setting_table.appendChild(arfcn_tr);
			this.setting_table.appendChild(band_tr);
			this.setting_table.appendChild(scs_tr);
			this.setting_table.appendChild(submit_btn);
		}

		render_neighborcell(){
			//clear neighborcell_table
			while (this.neighborcell_table.querySelector("tr")) {
				let remove = this.neighborcell_table.querySelector("tr")
				this.neighborcell_table.removeChild(remove);
			}
			var nr,lte,tr_left
			nr = this.config.NR;
			lte = this.config.LTE;
			for (let cell_info of nr) {
					this.create_nc_tr(1,cell_info);
				}
			for (let cell_info of lte) {
				this.create_nc_tr(0,cell_info);
			}

		}

		render_status(){
			//clear status_table
			while (this.status_table.querySelector("tr")) {
				this.status_table.removeChild(this.status_table.querySelector("tr"));
			}
			var status = this.config.lockcell_status;
			for (let key in status) {
				if (status[key] != ""){
					this.create_status_tr(key + ":" + status[key].toUpperCase());
				}
			}
		}

		create_status_tr(status){
			var tr = this.createTR();
			var td = this.createTD(status);
			tr.appendChild(td);
			this.status_table.appendChild(tr);
		}

		create_nc_tr(rat,cell_info){
			if (rat == 0) {
				var text = "LTE:";
			}
			else{
				var text = "NR:";
			}
			for (let key in cell_info) {
				if (cell_info[key] != ""){
					text += key + ":" + cell_info[key] + " ";
				}	
			}
			let tr_left = this.createTD(text);
			let tr_right = this.create_copy_btn_td(rat,cell_info.pci,cell_info.arfcn);
			let tr = this.createTR();
			tr.appendChild(tr_left);
			tr.appendChild(tr_right);
			this.neighborcell_table.appendChild(tr);
		}

		create_copy_btn_td(rat,pci,arfcn){
			var copy_btn = this.createBTN("<%:Copy%>",() => {
				this.pci_input.value = pci;
				this.arfcn_input.value = arfcn;
				this.rat_input.selectedIndex = rat;
				this.nr_options()
			});
			var td = document.createElement('td');
			td.className = "td cbi-section-table-cell left";
			td.setAttribute("width","10%");
			td.appendChild(copy_btn);
			
			return td;
		}

		cb_get(){
			this.render_neighborcell();
			this.render_status();
		}

		
	}

	class IMEI extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:Set IMEI%>");
			this.config_name = "imei";
			this.get_action = "get_imei";
			this.set_action = "set_imei";
			this.render();
		}

		render(){
			this.imei_input = this.createInput("imei",this.config);
			this.imei_btn = this.createBTN("<%:Submit%>",() => {
				this.set_config(this.imei_input.value);
			});
			this.fieldset.appendChild(this.imei_input);
			this.fieldset.appendChild(this.imei_btn);
		}

		cb_get(){
			this.imei_input.value = this.config;
		}

		cb_set(){
			this.imei_input.value = this.config;
		}

		update(){
			this.get_config();
		}
		
	}

	class RebootModem extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:Reboot Modem%>");
			this.config_name = "reboot_caps";
			this.get_action = "get_reboot_caps";
			this.set_action = "do_reboot";
			this.render();
		}

		cb_get(){
			this.soft_reboot_btn.disabled = !this.config.soft_reboot_caps;
			this.hard_reboot_btn.disabled = !this.config.hard_reboot_caps;
		}


		render(){
			this.soft_reboot_btn = this.createBTN("<%:Soft Reboot%>",() => {
					this.set_config('{"method":"soft"}');
				});
			this.hard_reboot_btn = this.createBTN("<%:Hard Reboot%>",() => {
				this.set_config('{"method":"hard"}');
			});
			this.fieldset.appendChild(this.soft_reboot_btn);
			this.fieldset.appendChild(document.createElement("br"));
			this.fieldset.appendChild(this.hard_reboot_btn);
			}
		update(){
			this.get_config();
		}
		
		
	}
	
	class AtDebug extends ModemConfig {
		constructor(cfg_id){
			super(cfg_id,"<%:AT Debug%>");
			this.config_name = "at_cfg";
			this.get_action = "get_at_cfg";
			this.set_action = "send_at";
			this.at_port=null;
			this.last_choice_cmd = null;
			this.render();
		}

		render(){
			this.textarea = document.createElement('textarea');
			this.textarea.style.width = "100%";
			this.textarea.style.height = "600px";
			this.textarea.readOnly = true;
			this.at_btn = this.createBTN("<%:Send%>",() => {
				let payload = {
					"at": this.at_input,
					"port": this.at_port
				}
				this.set_config(JSON.stringify(payload));
				//append input to textarea
				this.textarea.value += this.at_input +  " >> " + this.at_port + "\n";
			});
			this.clear_btn = this.createBTN("<%:Clear%>",() => {
				this.textarea.value = "";
			});
			this.clear_port_btn = this.createBTN("<%:Clear AT Port%>",() => {
				this.at_port_selector.value = "";
				this.at_port_selector.dispatchEvent(new Event('change'));
			});
			this.clear_cmd_btn = this.createBTN("<%:Clear AT Command%>",() => {
				this.cmd_prompt_selector.value = "";
				this.cmd_prompt_selector.dispatchEvent(new Event('change'));
			});
			var { input , selector } = this.createDroplistWithInput("at_port_selector","<%:Select Port%>" );
			selector.addEventListener("change",(event) => {
				this.at_port =  event.target.value;
			});
			this.at_port_selector = selector;
			this.at_port_input = input;
			var { input , selector } = this.createDroplistWithInput("cmd_prompt","<%:Input AT Command%>" );
			selector.addEventListener('change',(event) => {
				this.at_input = event.target.value;
			});
			this.cmd_prompt = input;
			this.cmd_prompt_selector = selector;
			
			var table = this.createTable();
			this.fieldset.appendChild(table);

			var tr,td_l,td_r;
			tr = this.createTR();
			td_l = this.createTD("<%:AT Port%>:");
			td_r = this.createTD();
			td_r.style.width = "70%";
			td_r.appendChild(this.at_port_selector);
			td_r.appendChild(this.at_port_selector.descr);
			td_r.appendChild(this.at_port_input);
			td_r.appendChild(this.at_port_input.descr);
			
			tr.appendChild(td_l);
			tr.appendChild(td_r);
			table.appendChild(tr);
			
			tr = this.createTR();
			td_l = this.createTD("<%:AT Command%>:");
			td_r = this.createTD();
			td_r.appendChild(this.cmd_prompt_selector);
			td_r.appendChild(this.cmd_prompt);
			td_r.appendChild(this.cmd_prompt.descr);
			td_r.appendChild(this.cmd_prompt_selector.descr);
			tr.appendChild(td_l);
			tr.appendChild(td_r);
			table.appendChild(tr);
			tr = this.createTR();
			td_l = this.createTD();
			td_l.appendChild(this.at_btn);
			td_l.appendChild(this.clear_port_btn);
			td_l.appendChild(this.clear_cmd_btn);
			tr.appendChild(td_l);
			table.appendChild(tr);
			this.fieldset.appendChild(table);
			this.fieldset.appendChild(this.textarea);
			this.fieldset.appendChild(this.clear_btn);
		}

		cb_get(){
			//clear ports
			while (this.at_port_selector.firstChild) {
				this.at_port_selector.removeChild(this.at_port_selector.firstChild);
			}
			//clear cmds
			while (this.cmd_prompt_selector.firstChild) {
				this.cmd_prompt_selector.removeChild(this.cmd_prompt_selector.firstChild);
			}

			//empty option
			var empty_option1=document.createElement("option");
			empty_option1.value = "";
			empty_option1.innerHTML = "<%:-- custom ---%>";
			var empty_option2=document.createElement("option");
			empty_option2.value = "";
			empty_option2.innerHTML = "<%:-- custom ---%>";
			this.cmd_prompt_selector.appendChild(empty_option1);
			this.at_port_selector.appendChild(empty_option2);
			var ports=this.config.ports;
			var other_ttys=this.config.other_ttys;
			var valid_ports=this.config.valid_ports;
			var using_port=this.config.using_port;
			var cmds = this.config.cmds;
			//append empty option to at_port_selector
			
			for (let port of other_ttys) {
				let select;
				let displayport = port;
				if (ports.includes(port) == false) {
					displayport += "<%:(Not belong to this modem)%>";
				}
				else{
					if (valid_ports.includes(port) == false) {
						displayport += "<%:(invalid)%>";
					}
					else{
						displayport += "<%:(valid)%>";
					}
					if (port == using_port) {
						displayport += "<%:(using)%>";
						select = true;
					}
				}
				
				
				var option = document.createElement('option');
				option.value = port;
				option.innerHTML = displayport;
				if (select) {
					option.selected = true;
					this.at_port = port;
				}
				this.at_port_selector.appendChild(option);
			}
			
			
			for (let cmd of cmds) {
				var option = document.createElement('option');
				option.value = cmd.value;
				option.innerHTML = cmd.name;
				this.cmd_prompt_selector.appendChild(option);
			}
			this.cmd_prompt_selector.dispatchEvent(new Event('change'));
			this.at_port_selector.dispatchEvent(new Event('change'));
			
			
		}
		
		cb_update(){
			//clear 2 input
			this.at_port_selector.value = "";
			this.cmd_prompt.value = "";
			this.get_config();
		}

		cb_set(){
			//append response to textarea
			this.textarea.value += this.config.res + "<<EOF\n";

		}
		
	}
	
	class Select_Modem {
		constructor(){
			this.modem_selector = document.getElementById('modem_selector');
			this.cfg_id = null;
			this.modem_cfg_list = [];
			this.create_modem_cfg_selector();
			this.update_modem_cfg_list();
		}
		
		create_modem_cfg_selector() {
			var selector = document.createElement('select');
			selector.addEventListener('change', (event) => {
				this.cfg_id = event.target.value;
				this.update_cfg_id(this.cfg_id);
			});
			this.modem_selector.appendChild(selector);
			this.selector = selector;
		}

		update_modem_cfg_list() {
			XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "get_modem_cfg")%>', {}, (x, data) => {
				var new_cfg_list = [];
				var cfgs = data.cfgs;
				for (let i = 0; i < cfgs.length; i++) {
					var cfg = cfgs[i];
					var name = cfg.name;
					var value = cfg.cfg;
					new_cfg_list.push({ "value": value, "name": name });
				}
				if (JSON.stringify(new_cfg_list) != JSON.stringify(this.modem_cfg_list)) {
					this.cfg_options = new_cfg_list;
				}
			});
		}

		set cfg_options(value) {
			var longger = this.modem_cfg_list.length > value.length ? this.modem_cfg_list : value;
			if (longger.length == 0) {
				return;
			}
			for (let i = 0; i < longger.length; i++) {
				var option = this.selector.options[i];
				if (i < value.length) {
					if (i >= this.selector.options.length) {
						option = document.createElement('option');
						this.selector.appendChild(option);
					}
					option.value = value[i].value;
					option.innerHTML = value[i].name;

				}
				else {
					this.selector.removeChild(option);
				}
			}
			this.cfg_id = this.selector.value;
			this.modem_cfg_list = value;
			this.update_cfg_id(this.cfg_id);
		}
	}

	class TabMenu extends Select_Modem {
		functions = {
				"DialMode": {"class": DialMode, "name":"<%:Dial Mode%>"},
				"RatPrefer": {"class": RatPrefer, "name":"<%:Rat Prefer%>"},
				"IMEI": {"class": IMEI, "name": "<%:Set IMEI%>"},
				"NeighborCell": {"class": NeighborCell, "name": "<%:Neighbor Cell%>"},
				"LockBand": {"class": Lockband, "name":"<%:Lock Band%>"},
				"RebootModem": {"class": RebootModem, "name":"<%:Reboot Modem%>"},
				"AtDebug": {"class": AtDebug, "name":"<%:AT Debug%>"}
			}
		constructor(){
			super();
			this.cbi_map = document.querySelector('.cbi-map');
			this.class_map = {};
			this.datatabs = [];
			this.disabled_features = [];
			this.hotplug_elements = [];
			//this.create_tabmenu();
			
		}

		update_cfg_id(cfg_id){
			XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "modem_ctrl")%>', { "cfg": cfg_id , "action" : "get_disabled_features"}, (x, data) => {
				//clear class_map
				
				this.disabled_features = data.disabled_features ? data.disabled_features : [];
				//delete tabmenu
				for (let element of this.hotplug_elements){
					element.parentNode.removeChild(element);
				}

				this.class_map = {};
				this.datatabs = [];
				this.hotplug_elements = [];
				this.create_tabmenu();
				for (let key in this.class_map) {
					this.class_map[key].cfg_id = cfg_id;
					this.class_map[key].get_config();
				}
				//check if all datatab not selected
				for (let tab of this.datatabs) {
					if (tab.className == "cbi-tab") {
						this.switch_tab(tab);
						return;
					}
				}
				this.switch_tab(this.datatabs[0]);
				});
		}

		create_tabmenu(){
			//add support function to tabmenu
			var tabmenu = document.createElement('ul');
			this.hotplug_elements.push(tabmenu);
			tabmenu.className = "cbi-tabmenu";
			for (let key in this.functions) {
				if (this.disabled_features.includes(key)) {
					continue;
				}
				var li = document.createElement('li');
				li.className = "cbi-tab-disabled";
				li.innerHTML = this.functions[key].name;
				li.setAttribute("data-tab", key);
				li.addEventListener('click', (event) => {
					this.switch_tab(event.target)
				});
				tabmenu.appendChild(li);
				this.datatabs.push(li);
			}
			this.cbi_map.appendChild(tabmenu);
		}

		switch_tab(target){
			target.className = "cbi-tab";
			target.style.display = "";
			var datatab = target.getAttribute("data-tab");
			for (let i = 0; i < this.datatabs.length; i++) {
				if (this.datatabs[i] != target) {
					this.datatabs[i].className = "cbi-tab-disabled";
				}
			}

			if (this.class_map[datatab] == undefined) {
				this.class_map[datatab] = new this.functions[datatab].class(this.cfg_id);
				this.hotplug_elements.push(this.class_map[datatab].fieldset);
			}
			for (let key in this.class_map) {
				this.class_map[key].hide();
			}
			this.class_map[datatab].show();
		}

	
	}

	
	window.onload = function(){
		var tabmenu = new TabMenu();
	}

</script>
<style>
	.cbi-tabmenu li {
		padding: 0.5rem;
	}

	.band-container {
		display: flex;
		margin-top: 1rem;
		align-items: center;
		min-width: 15%;
	}
</style>
<div class="cbi-map">
	<fieldset class="cbi-section">
		<table class="table">
			<tbody>
				<tr class="tr">
					<td class="td" width="33%"><%:Modem Name%></td>
					<td class="td" id="modem_selector">

					</td>
				</tr>
			</tbody>
		</table>
	</fieldset>
</div>
<%+footer%>
